package com.hxexp.weixin.mvc.bindpassenger.service.impl;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.hxexp.weixin.common.cache.PassengerCacheManager;
import com.hxexp.weixin.common.cache.PassengerTicketCacheManager;
import com.hxexp.weixin.common.cache.model.PassengerTicketInfo;
import com.hxexp.weixin.common.exception.APIException;
import com.hxexp.weixin.common.exception.ServiceException;
import com.hxexp.weixin.constant.StringConstant;
import com.hxexp.weixin.constant.TicketState;
import com.hxexp.weixin.hpe.api.bindpassenger.BindPassengerAPI;
import com.hxexp.weixin.hpe.api.bindpassenger.model.BindPassengerParamBean;
import com.hxexp.weixin.hpe.api.bindpassenger.model.BindPassengerResultBean;
import com.hxexp.weixin.hpe.api.orderdetail.model.OrderDetailResultBean;
import com.hxexp.weixin.hpe.api.orderdetail.model.OrderTicketInfoBean;
import com.hxexp.weixin.hpe.api.passengerlist.model.PassengerBean;
import com.hxexp.weixin.mvc.bindpassenger.model.BindPassengerAjaxResult;
import com.hxexp.weixin.mvc.bindpassenger.service.BindPassengerService;
import com.hxexp.weixin.mvc.order.service.OrderService;

import net.sf.cglib.beans.BeanCopier;

/**
 * 绑定乘客实现类
 *
 * @author wang.bin
 * @author li.jiang
 */
@Service
public class BindPassengerServiceImpl implements BindPassengerService {
    private BeanCopier beanCopier = BeanCopier.create(BindPassengerResultBean.class, BindPassengerAjaxResult.class, false);
    private BeanCopier beanCopier2 = BeanCopier.create(OrderDetailResultBean.class, PassengerTicketInfo.class, false);
    private BeanCopier beanCopier3 = BeanCopier.create(PassengerBean.class, PassengerTicketInfo.class, false);

    @Autowired
    private BindPassengerAPI bindPassengerAPI;
    @Autowired
    private OrderService orderService;
    @Autowired
    PassengerCacheManager passengersCacheManager;
    @Autowired
    PassengerTicketCacheManager pticketCacheManager;

    @Override
    public BindPassengerAjaxResult bindPassenger(String orderId, String passengerIds, String userId) throws ServiceException {
        String _passengerIds = passengerIds; // NOSONAR
        // 当前台只选中用户自己的乘客信息时，为了避免绑定乘客的参数为NULL,将passengerIds设置成“”
        if (",".equals(_passengerIds)) {
            _passengerIds = "";
        }
        String[] passengerIdArray = _passengerIds.split(",");
        List<String> passengerIdList = Arrays.asList(passengerIdArray);

        // 查询订单详情
        OrderDetailResultBean orderDetail = orderService.getOrderDetail(orderId);

        String message = "";
        // 乘客已购车票map
        Map<String, String> passengerTicketInfoMap = new HashMap<String, String>();
        // 检查乘客是否已购买过车票
        message = checkPassengerTicket(userId, passengerIdList, passengerTicketInfoMap, orderDetail);

        BindPassengerAjaxResult bindPassengerAjaxResult = new BindPassengerAjaxResult();
        // 未购买过该车次车票，进行乘客绑定订单操作
        if (StringConstant.BLANK.equals(message)) {
            return bindPassenger2Order(orderId, passengerIdList, passengerTicketInfoMap);
        } else {
            // 如果乘客之前有购买过该车次车票，直接返回错误提示信息
            message += "已购买该车次车票，不能重复购票";
            bindPassengerAjaxResult.setErrcode(-1);
            bindPassengerAjaxResult.setErrmsg(message);
            return bindPassengerAjaxResult;
        }
    }

    /**
     * 绑定乘客到订单
     *
     * @param orderId
     *            订单号
     * @param passengerIdList
     *            乘客ID列表
     * @param passengerTicketInfoMap
     *            乘客已购车票map
     * @return 绑定乘客结果
     * @throws ServiceException
     */
    private BindPassengerAjaxResult bindPassenger2Order(String orderId, List<String> passengerIdList, Map<String, String> passengerTicketInfoMap)
            throws ServiceException {
        BindPassengerAjaxResult bindPassengerAjaxResult = new BindPassengerAjaxResult();
        BindPassengerParamBean bindPassengerParamBean = new BindPassengerParamBean();
        BindPassengerResultBean bindPassengerResultBean = new BindPassengerResultBean();

        bindPassengerParamBean.setOrderId(orderId);
        bindPassengerParamBean.setPassengerIds(passengerIdList);

        try {
            bindPassengerResultBean = bindPassengerAPI.bindPassenger(bindPassengerParamBean);
        } catch (APIException e) {
            throw new ServiceException(e);
        }

        beanCopier.copy(bindPassengerResultBean, bindPassengerAjaxResult, null); // javabean值拷贝
        String passengerTicketInfosCSV = StringUtils.collectionToCommaDelimitedString(passengerTicketInfoMap.entrySet());
        try {
            passengerTicketInfosCSV = URLEncoder.encode(passengerTicketInfosCSV, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new ServiceException(e);
        }
        bindPassengerAjaxResult.setPassengerTicketInfos(passengerTicketInfosCSV);

        return bindPassengerAjaxResult;
    }
    /**
     * 检查乘客是否已购买过车票
     *
     * @param userId
     * @param passengerIdList
     * @param passengerTicketInfoMap
     * @param orderDetail
     * @return
     * @throws ServiceException
     */
    private String checkPassengerTicket(String userId, List<String> passengerIdList, Map<String, String> passengerTicketInfoMap,
                                        OrderDetailResultBean orderDetail) throws ServiceException {
        String message = "";

        for (String passengerId : passengerIdList) {
            if (StringUtils.isEmpty(passengerId) || StringConstant.USER_OTHER_PASSENGERID.equals(passengerId)) {
                passengerId = userId;
            }
            // 乘客已购车票信息
            PassengerTicketInfo passengerTicketInfo = new PassengerTicketInfo();
            PassengerBean passenger = passengersCacheManager.get(passengerId);
            beanCopier2.copy(orderDetail, passengerTicketInfo, null);
            beanCopier3.copy(passenger, passengerTicketInfo, null);

            String key = pticketCacheManager.generateKey(passengerTicketInfo.toString());
            String purchasedTicketOrderId = pticketCacheManager.get(key);

            // 乘客已购买该车次车票
            if (purchasedTicketOrderId != null) {
                boolean isRefunded = false; // 是否已退票
                // 已购车票的订单详情
                OrderDetailResultBean purchasedTicketOrderDetail = orderService.getOrderDetail(purchasedTicketOrderId);
                List<OrderTicketInfoBean> purchasedTicketList = purchasedTicketOrderDetail.getTicketList();
                isRefunded = passengerIsRefunded(purchasedTicketList, passenger);

                if (isRefunded) {
                    passengerTicketInfoMap.put(key, orderDetail.getOrderId());
                } else {
                    String fullname = passenger.getFullname();
                    message += "乘客：" + fullname + "，";
                }
            } else {
                passengerTicketInfoMap.put(key, orderDetail.getOrderId());
            }
        }

        return message;
    }

    /**
     * 乘客是否已退票
     *
     * @param purchasedTicketList
     *            已售车票列表
     * @param passenger
     *            乘客信息
     * @return true: 已退票；false: 未退票
     */
    private boolean passengerIsRefunded(List<OrderTicketInfoBean> purchasedTicketList, PassengerBean passenger) {
        boolean isRefunded = false;
        for (OrderTicketInfoBean ticket : purchasedTicketList) {
            if (passenger.getIdentificationType().equals(ticket.getIdentificationType())
                    && passenger.getIdentificationNumber().equals(ticket.getIdentificationNumber())) {
                if (TicketState.REFUNDED.equals(ticket.getTicketState())) {
                    isRefunded = true;
                }
                break;
            }
        }

        return isRefunded;
    }
}
